package com.jinghua.treatment.wechat.controller;

import com.alibaba.fastjson.JSONObject;
import com.jinghua.treatment.common.GlobalConstant;
import com.jinghua.treatment.common.controller.BaseController;
import com.jinghua.treatment.common.domain.JSONResult;
import com.jinghua.treatment.common.exception.BizException;
import com.jinghua.treatment.entity.PayHistory;
import com.jinghua.treatment.entity.SysPatient;
import com.jinghua.treatment.service.SysPatientService;
import com.jinghua.treatment.tools.IDGenerator;
import com.jinghua.treatment.tools.PropertyUtil;
import com.jinghua.treatment.wechat.entity.JSPayConfig;
import com.jinghua.treatment.wechat.service.PayService;
import com.jinghua.treatment.wechat.util.HttpUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * 微信支付
 */
@Controller
@RequestMapping("/wcpay")
public class PayController extends BaseController{

    @Resource
    private SysPatientService sysPatientService;
    @Resource
    private PayService payService;

    int cont;

    @ApiOperation(value="前端支付")
    @RequestMapping(value="/jspayConfig")
    @ResponseBody
    public JSONResult jspayConfig(String phone) {
        JSPayConfig  jsPayConfig = new JSPayConfig();

       return null;
    }

    @ApiOperation(value="统一下单")
    @RequestMapping(value="/wcorder")
    @ResponseBody
    public JSONResult wcorder(String patientId,Model model,Double money,String title) {
        if(StringUtils.isEmpty(patientId)||StringUtils.isEmpty(money)){
            throw new BizException("参数丢失");
        }
        SysPatient sysPatient  = sysPatientService.selectById(Integer.parseInt(patientId));
        String moneyStr = Math.round(money*100)+"";//以分为单位
        logger.debug("moneyStr："+moneyStr);
        System.out.println("moneyStr："+moneyStr);
        String openId = sysPatient.getWechat();
        // 微信统一下单接口
        TreeMap<String, String> xmlData = new TreeMap<String, String>();
        xmlData.put("appid", PropertyUtil.getConfig("wechat.appId"));
        xmlData.put("attach", "杏林名家");
        xmlData.put("body", StringUtils.isEmpty(title)?"杏林名家-客户订单":"杏林名家-"+title);
        xmlData.put("mch_id",PropertyUtil.getConfig("wcpay.mchId"));//商户号
        xmlData.put("nonce_str", IDGenerator.uuid().substring(0,16));
        xmlData.put("out_trade_no", IDGenerator.uuid().substring(0,10));
        xmlData.put("spbill_create_ip", getAddrIp(request));
        //xmlData.put("total_fee", moneyStr);
        xmlData.put("total_fee", 1+"");
        xmlData.put("trade_type", "JSAPI");
        xmlData.put("openid", openId);
        xmlData.put("notify_url", PropertyUtil.getConfig("wcpay.mchId")+"/wcpay/notify");

        //签名
        String sign = getSign(xmlData, PropertyUtil.getConfig("wcpay.key"));
        xmlData.put("sign", sign);
        String xml = mapToXml(xmlData);
        String xmlStr = HttpUtil.sendPostRequest("https://api.mch.weixin.qq.com/pay/unifiedorder",xml);
        System.out.println("############    统一下单返回  xmlStr      ################ \n"+xmlStr);

        //创建SAXReader对象
        SAXReader reader = new SAXReader();
        //读取文件 转换成Document
        StringReader  stringReader  = new StringReader(xmlStr);
        Document document = null;
        try {
            document = reader.read(stringReader);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        //获取根节点元素对象
        Element root = document.getRootElement();
        if("FAIL".equalsIgnoreCase(root.element("result_code").getText()))
            throw new BizException("微信统一下单失败");


        //封装前端代码
        TreeMap  params  = new TreeMap();
        params.put("appId", PropertyUtil.getConfig("wechat.appId"));
        params.put("nonceStr",IDGenerator.uuid().substring(0,16));
        params.put("signType","MD5");
        params.put("package","prepay_id="+root.element("prepay_id").getText());
        params.put("timeStamp",Long.toString(System.currentTimeMillis() / 1000));
        String newPaySign = null;

        Set<String>  keys = params.keySet();
        for(String key:keys){
            logger.debug("params====>"+key+":"+params.get(key));
        }
        newPaySign = getSign(params,  PropertyUtil.getConfig("wcpay.key"));
        params.put("paySign",newPaySign);
        return jsonResult(GlobalConstant.SUCCESS_CODE,"ok",params);
    }

    @ApiOperation(value="支付回调")
    @RequestMapping(value="/notify")
    @ResponseBody
    public void notify(String patientId) {
        System.out.println("支付回调");
        try {
            InputStream is   =  request.getInputStream();
            BufferedReader br   = new BufferedReader(new InputStreamReader(is));
            String line  = null;
            System.out.println("\n\n\n##################"+cont+"\n");
            while((line=br.readLine())!=null){
                System.out.println(line);
            }
            cont++;
            this.response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value="统一下单获取用户,临时用")
    @RequestMapping(value="/wcuser")
    public String order(String code,Model  model) {
        String openid = null;
        if(code!=null) {//用code 换access_token
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + PropertyUtil.getConfig("wechat.appId") + "&secret=" + PropertyUtil.getConfig("wechat.secret") + "&code=" + code + "&grant_type=authorization_code";
            String json = HttpUtil.sendGetRequest(url, null);
            System.out.println("json："+json);
            JSONObject jsonObject = JSONObject.parseObject(json);
            if(jsonObject!=null&&jsonObject.get("access_token")!=null){
                openid = (String)jsonObject.get("openid");
            }
        }
        return "redirect:/wcpay/product.html?openid="+openid;
    }


    @ApiOperation(value="统一下单,临时用")
    @RequestMapping(value="/order")
    @ResponseBody
    public JSONResult order(Double money,String openid,Model  model) {

        if(openid!=null){
            String moneyStr = Math.round(money*100)+"";//以分为单位
            logger.debug("moneyStr："+moneyStr);
            System.out.println("moneyStr："+moneyStr);

            // 微信统一下单接口
            String out_trade_no = IDGenerator.uuid().substring(0,10);
            TreeMap<String, String> xmlData = new TreeMap<String, String>();
            xmlData.put("appid", PropertyUtil.getConfig("wechat.appId"));
            xmlData.put("attach", "杏林名家");
            xmlData.put("body", "杏林名家-客户订单");
            xmlData.put("mch_id",PropertyUtil.getConfig("wcpay.mchId"));//商户号
            xmlData.put("nonce_str", IDGenerator.uuid().substring(0,16));
            xmlData.put("out_trade_no",out_trade_no );
            xmlData.put("spbill_create_ip", getAddrIp(request));
            xmlData.put("total_fee", moneyStr);
            //xmlData.put("total_fee", 1+"");
            xmlData.put("trade_type", "JSAPI");
            xmlData.put("openid", openid);
            xmlData.put("notify_url", PropertyUtil.getConfig("wcpay.mchId")+"/wcpay/notify");

            //签名
            String sign = getSign(xmlData, PropertyUtil.getConfig("wcpay.key"));
            xmlData.put("sign", sign);
            String xml = mapToXml(xmlData);
            String xmlStr = HttpUtil.sendPostRequest("https://api.mch.weixin.qq.com/pay/unifiedorder",xml);
            System.out.println("############    统一下单返回  xmlStr      ################ \n"+xmlStr);

            //创建SAXReader对象
            SAXReader reader = new SAXReader();
            //读取文件 转换成Document
            StringReader  stringReader  = new StringReader(xmlStr);
            Document document = null;
            try {
                document = reader.read(stringReader);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            //获取根节点元素对象
            Element root = document.getRootElement();
            if("FAIL".equalsIgnoreCase(root.element("result_code").getText()))
                throw new BizException("微信统一下单失败");


            //插入支付记录
            PayHistory  payHistory = new PayHistory();
            payHistory.setPayFlowId(out_trade_no);
            payHistory.setWcOrderId(root.element("prepay_id").getText());
            payHistory.setPayAccount(openid);
            payHistory.setPayMoney(money);
            payHistory.setPayStatus("wait");
            payHistory.setPayTime(new Date());
            payHistory.setUuid(IDGenerator.uuid());

            payService.savePayHistory(payHistory);

            //封装前端代码
            TreeMap  params  = new TreeMap();
            params.put("appId", PropertyUtil.getConfig("wechat.appId"));
            params.put("nonceStr",IDGenerator.uuid().substring(0,16));
            params.put("signType","MD5");
            params.put("package","prepay_id="+root.element("prepay_id").getText());
            params.put("timeStamp",Long.toString(System.currentTimeMillis() / 1000));
            String newPaySign = null;
            newPaySign = getSign(params,  PropertyUtil.getConfig("wcpay.key"));
            params.put("paySign",newPaySign);
            params.put("money",money);
            model.addAttribute("params",params);
            return jsonResult(GlobalConstant.SUCCESS_CODE,"ok",params);
        }

        return jsonResult(GlobalConstant.FAIL_CODE,"fail",null);
    }


    @ApiOperation(value="更新支付状态")
    @RequestMapping(value="/updatePayStatus")
    @ResponseBody
    public void updatePayStatus(String orderId,String status){
        if(StringUtils.isEmpty(orderId)||StringUtils.isEmpty(status))
            throw new BizException("参数丢失");
        orderId = orderId.replace("prepay_id=","");
        PayHistory payHistory = payService.findPayHistoryByOrderId(orderId);
        payHistory.setPayStatus(status);
        payService.updatePayHistoryByEample(payHistory);
    }


    /**
     * 对数据签名
     * @param xmlData
     * @param paternerKey
     * @return
     */
    private String getSign(TreeMap<String, String> xmlData, String paternerKey ) {
        String signStr ="";
        Set<String>  keys = xmlData.keySet();
        for(String key:keys){
            signStr+=key+"="+xmlData.get(key)+"&";
        }
        String stringSignTemp = signStr + "key=" + paternerKey;
        String signValue = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
        return  signValue;
    }


    /**
     * map转成xml
     * @param arr
     * @return
     */
    public String mapToXml(Map<String, String> arr) {
        String xml = "<xml>";
        Set<String>    keys =   arr.keySet();
        for(String key:keys){
            xml += "<" + key + ">" + arr.get(key) + "</" + key + ">";
        }
        xml += "</xml>";
        return xml;
    }

    /**
     * 获取请求IP地址
     * @param request
     * @return
     */
    private String getAddrIp(HttpServletRequest request){
        return request.getRemoteAddr();
    }

}
